﻿using System;
using System.Collections.Generic;
using System.Windows;

namespace Domotica.Gazing.Calibration
{

    #region

    internal abstract class Process
    {
        public abstract bool DoProcess(Calibrator calibrator);

        public virtual void OnFaceMove(GazeEventArgs e)
        {
        }

        public virtual void OnGazeClick(GazeClickEventArgs e)
        {
        }

        public virtual void OnGazeClickElapsed(GazeClickElapsedEventArgs args, Calibrator calibrator)
        {
        }
    }

    internal class ProcessList : List<Process>
    {
    }

    #endregion

    #region

    internal class ProcessSetForm : Process
    {
        private readonly Point _Position;

        public ProcessSetForm(Point position)
        {
            _Position = position;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            calibrator.FormSetLocation(_Position);
            return true;
        }
    }

    #endregion

    #region

    internal class ProcessSetFormTopText : Process
    {
        private readonly string _Text;

        public ProcessSetFormTopText(String text)
        {
            _Text = text;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            calibrator.FormSetTopText(_Text);
            return true;
        }
    }

    #endregion

    #region

    internal class ProcessSetFormMiddleText : Process
    {
        private readonly string _Text;

        public ProcessSetFormMiddleText(String text)
        {
            _Text = text;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            calibrator.FormSetMiddleText(_Text);
            return true;
        }
    }

    #endregion

    #region

    internal class ProcessSetFormBottomText : Process
    {
        private readonly string _Text;

        public ProcessSetFormBottomText(String text)
        {
            _Text = text;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            calibrator.FormSetBottomText(_Text);
            return true;
        }
    }

    #endregion

    #region

    internal class ProcessCursorShow : Process
    {
        private readonly bool _Show;

        public ProcessCursorShow(bool show)
        {
            _Show = show;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            if (_Show)
            {
                calibrator.FormShow();
            }
            else
            {
                calibrator.FormHide();
            }
            return true;
        }
    }

    #endregion

    #region

    internal class ProcessWait : Process
    {
        private readonly int _Milliseconds;
        private bool _First;
        private DateTime _Start;

        public ProcessWait(int miliSeconds)
        {
            _Milliseconds = miliSeconds;
            _First = true;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            if (_First)
            {
                _First = false;
                _Start = DateTime.Now;
            }
            return (DateTime.Now - _Start).TotalMilliseconds >= _Milliseconds;
        }
    }

    #endregion

    #region

    internal class ProcessGazeClick : Process
    {
        private bool _Clicked;
        private readonly ProcessGazeClickCallBack _Callback;

        public ProcessGazeClick(ProcessGazeClickCallBack callback)
        {
            _Callback = callback;
        }


        public override bool DoProcess(Calibrator calibrator)
        {
            if (_Clicked)
            {
                calibrator.FormSetBottomText("");
            }
            return _Clicked;
        }

        public override void OnGazeClick(GazeClickEventArgs e)
        {
            if (!_Clicked)
            {
                if (_Callback != null)
                {
                    _Callback(e);
                }
                _Clicked = true;
            }
        }

        public override void OnGazeClickElapsed(GazeClickElapsedEventArgs e, Calibrator calibrator)
        {
            calibrator.FormSetMiddleText((e.Elapsed/1000).ToString());
            if (e.Elapsed > 500)
            {

                if (_Callback != null)
                {
                    _Callback(e);
                }
                _Clicked = true;
            }
        }
    }

    public delegate void ProcessGazeClickCallBack(GazeClickEventArgs e);

    #endregion

    #region

    internal class ProcessFormMove : Process
    {
        private readonly int _Milliseconds;
        private bool _First;
        private double _Height;
        private DateTime _Start;
        private Point _ToPoint;
        private double _Width;

        public ProcessFormMove(Point toPoint, int miliSeconds)
        {
            _Milliseconds = miliSeconds;
            _First = true;
            _ToPoint = toPoint;
        }

        public override bool DoProcess(Calibrator calibrator)
        {
            if (_First)
            {
                _First = false;
                _Start = DateTime.Now;
                Point startPoint = calibrator.FormGetLocation();
                _Width = startPoint.X - _ToPoint.X;
                _Height = startPoint.Y - _ToPoint.Y;
            }
            var elapsed = (int) (DateTime.Now - _Start).TotalMilliseconds;
            if (elapsed > _Milliseconds)
            {
                calibrator.FormSetLocation(_ToPoint);
                return true;
            }

            var p = new Point(
                _Width - ((_Width*elapsed)/_Milliseconds) + _ToPoint.X,
                _Height - ((_Height*elapsed)/_Milliseconds) + _ToPoint.Y);
            calibrator.FormSetLocation(p);

            return false;
        }
    }

    #endregion
}